home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / hoobie / ciscocrack.c < prev    next >
C/C++ Source or Header  |  2001-11-06  |  20KB  |  591 lines

  1.  
  2.  
  3. #! /bin/sh
  4. ## Decrypts cisco "encrypted" passwords.  Feed this confg files as stdin.
  5. ## Anything that looks like a "type 7 encrypted" string gets decrypted.
  6. ## This should really be a C program, but is presented as a script just to
  7. ## piss off a certain group of people.  One beer, please...
  8.  
  9. while read xx ; do
  10.   case "$xx" in
  11.     *d\ 7\ [01]??* ) ;;
  12.     *) continue ;;
  13.   esac
  14.   DEC=`echo "$xx" | sed -e 's/.* //' -e 's/\(^..\).*/\1/'`
  15.   DP1=`expr $DEC + 1`
  16.   HEX=`echo "$xx" | sed -e 's/.* //' -e 's/^..\(..*\)/\1/'`
  17.   echo 'dsfd;kfoA,.iyewrkldJKDHSUB' | cut -c "${DP1}-30" >
  18. /tmp/cis$$.pad
  19.   echo '#' > /tmp/cis$$.in
  20.   for xx in 1-2 3-4 5-6 7-8 9-10 11-12 13-14 15-16 17-18 19-20 21-22 ;
  21. do
  22.     echo "${HEX}" | cut -c $xx | sed -e '/^$/q' -e 's/^/0x/' >>
  23. /tmp/cis$$.in
  24.   done
  25.   echo -n "${DEC}${HEX}: "
  26.   data -g < /tmp/cis$$.in | xor /tmp/cis$$.pad
  27.   echo ''
  28. done
  29. rm -f /tmp/cis$$.pad /tmp/cis$$.in
  30. exit 0
  31.  
  32. # Discussion:
  33.  
  34. # When "service password-encryption" is configured into a cisco router and
  35. # the configuration subsequently viewed, the passwords are no longer printed
  36. # as plaintext but as strings of randomish-looking garbage.  Analysis of
  37. # several samples reveals the scrambling algorithm to be trivially weak.
  38. # Dr. Delete derived and published an analysis and decryption program some
  39. # time ago, but since that didn't seem to be generally available at the time
  40. # I went looking for it, here is an independent explanation.  This was worked
  41. # out on PAPER over a plate of nachos in a hotel bar in downtown LA, but
  42. # still illustrates where a general-purpose "xor" handler can be useful for
  43. # quickly cracking lame "proprietary" algorithms of this genre.
  44. # Passwords can be up to eleven mixed-case characters.  In the "encrypted"
  45. # representation, the first two bytes of the long string are a random decimal
  46. # offset between 0 and 15 into a magic block of characters, and the remaining
  47. # bytes are ascii-hex representations of the password bytes xored against
  48. # the character-block bytes from the given offset on down.  The character
  49. # block is "dsfd;kfoA,.iyewrkldJKDHSUB", which is enough for a maximum-length
  50. # password at the maximum offset.
  51.  
  52. # Another character block consisting of "sgvca69834ncxv9873254k;fg87" is
  53. # located after the first one in the IOS image, which may be relevant to
  54. # something else and is simply mentioned here for posterity.  It is also
  55. # interesting to note that the strings "%02d" and "%02x" occur immediately
  56. # afterward, which in light of the above is another clue.
  57.  
  58.  
  59. --------------------------------------------------------------------
  60.  
  61.  
  62. --- SNIP ---
  63. > # Dr. Delete derived and published an analysis and decryption program some
  64. > # time ago, but since that didn't seem to be generally available at the time
  65. > # I went looking for it, here is an independent explanation.  This was worked
  66. > # out on PAPER over a plate of nachos in a hotel bar in downtown LA, but
  67. --- SNIP ---
  68.  
  69. Maybe this is the program you are refering to... But maybe not...
  70. However, it is in C...
  71.  
  72. I'm not sure, but it might not work for 11.x IOS (I cannot verify this at
  73. the moment, and I know that something didn't work but I cannot remember
  74. what :-))
  75.  
  76. -------- ciscocrack.c --------
  77.  
  78. #include <stdio.h>
  79. #include <ctype.h>
  80.  
  81. char xlat[] = {
  82.         0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f,
  83.         0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72,
  84.         0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44
  85. };
  86.  
  87. char pw_str1[] = "password 7 ";
  88. char pw_str2[] = "enable-password 7 ";
  89.  
  90. char *pname;
  91.  
  92. cdecrypt(enc_pw, dec_pw)
  93. char *enc_pw;
  94. char *dec_pw;
  95. {
  96.         unsigned int seed, i, val = 0;
  97.  
  98.         if(strlen(enc_pw) & 1)
  99.                 return(-1);
  100.  
  101.         seed = (enc_pw[0] - '0') * 10 + enc_pw[1] - '0';
  102.  
  103.         if (seed > 15 || !isdigit(enc_pw[0]) || !isdigit(enc_pw[1]))
  104.                 return(-1);
  105.  
  106.         for (i = 2 ; i <= strlen(enc_pw); i++) {
  107.                 if(i !=2 && !(i & 1)) {
  108.                         dec_pw[i / 2 - 2] = val ^ xlat[seed++];
  109.                         val = 0;
  110.                 }
  111.  
  112.                 val *= 16;
  113.  
  114.                 if(isdigit(enc_pw[i] = toupper(enc_pw[i]))) {
  115.                         val += enc_pw[i] - '0';
  116.                         continue;
  117.                 }
  118.  
  119.                 if(enc_pw[i] >= 'A' && enc_pw[i] <= 'F') {
  120.                         val += enc_pw[i] - 'A' + 10;
  121.                         continue;
  122.                 }
  123.  
  124.                 if(strlen(enc_pw) != i)
  125.                         return(-1);
  126.         }
  127.  
  128.         dec_pw[++i / 2] = 0;
  129.  
  130.         return(0);
  131. }
  132.  
  133. usage()
  134. {
  135.         fprintf(stdout, "Usage: %s -p <encrypted password>\n", pname);
  136.         fprintf(stdout, "       %s <router config file> <output file>\n", pname);
  137.  
  138.         return(0);
  139. }
  140.  
  141. main(argc,argv)
  142. int argc;
  143. char **argv;
  144.  
  145. {
  146.         FILE *in = stdin, *out = stdout;
  147.         char line[257];
  148.         char passwd[65];
  149.         unsigned int i, pw_pos;
  150.  
  151.         pname = argv[0];
  152.  
  153.         if(argc > 1)
  154.         {
  155.                 if(argc > 3) {
  156.                         usage();
  157.                         exit(1);
  158.                 }
  159.  
  160.                 if(argv[1][0] == '-')
  161.                 {
  162.                         switch(argv[1][1]) {
  163.                                 case 'h':
  164.                                 usage();
  165.                                 break;
  166.  
  167.                                 case 'p':
  168.                                 if(cdecrypt(argv[2], passwd)) {
  169.                                         fprintf(stderr, "Error.\n");
  170.                                         exit(1);
  171.                                 }
  172.                                 fprintf(stdout, "password: %s\n", passwd);
  173.                                 break;
  174.  
  175.                                 default:
  176.                                 fprintf(stderr, "%s: unknow option.", pname);
  177.                         }
  178.  
  179.                         return(0);
  180.                 }
  181.  
  182.                 if((in = fopen(argv[1], "rt")) == NULL)
  183.                         exit(1);
  184.                 if(argc > 2)
  185.                         if((out = fopen(argv[2], "wt")) == NULL)
  186.                                 exit(1);
  187.         }
  188.  
  189.         while(1) {
  190.                 for(i = 0; i < 256; i++) {
  191.                         if((line[i] = fgetc(in)) == EOF) {
  192.                                 if(i)
  193.                                         break;
  194.  
  195.                                 fclose(in);
  196.                                 fclose(out);
  197.                                 return(0);
  198.                         }
  199.                         if(line[i] == '\r')
  200.                                 i--;
  201.  
  202.                         if(line[i] == '\n')
  203.                                 break;
  204.                 }
  205.                 pw_pos = 0;
  206.                 line[i] = 0;
  207.  
  208.                 if(!strncmp(line, pw_str1, strlen(pw_str1)))
  209.                         pw_pos = strlen(pw_str1);
  210.  
  211.                 if(!strncmp(line, pw_str2, strlen(pw_str2)))
  212.                         pw_pos = strlen(pw_str2);
  213.  
  214.                 if(!pw_pos) {
  215.                         fprintf(stdout, "%s\n", line);
  216.                         continue;
  217.                 }
  218.  
  219.                 if(cdecrypt(&line[pw_pos], passwd)) {
  220.                         fprintf(stderr, "Error.\n");
  221.                         exit(1);
  222.                 }
  223.                 else {
  224.                         if(pw_pos == strlen(pw_str1))
  225.                                 fprintf(out, "%s", pw_str1);
  226.                         else
  227.                                 fprintf(out, "%s", pw_str2);
  228.  
  229.                         fprintf(out, "%s\n", passwd);
  230.                 }
  231.         }
  232. }
  233. ---- END OF ciscocrack.c -----
  234.  
  235. Gr. Arjan
  236.  
  237.  
  238.  
  239.  
  240. ---------------------------------------------------------------------
  241.  
  242.  
  243. The Shell script that was posted was originally written by Hobbit
  244. (hobbit@avian.org) and is available from ftp://avian.org.
  245.  
  246. The C code I believe originally came from SPHiXe and has been floating
  247. around for some time.
  248.  
  249. Yes, they both should work on 11.x.
  250.  
  251. For those who want to save the time here's what cisco is doing (just so
  252. you can do a lot of it in your head):
  253.  
  254. Assume the following :
  255.  
  256. Password 7 08204E
  257.  
  258. The encrypted string is 08204E. It must be an even length of digits and
  259. the first two digits are used as a base 10 index into the XOR string. The
  260. length of the plaintext password is strlen(enc_pw) -2 / 2. In this case 2
  261. chars.
  262.  
  263. 08 is the index into the xor string.
  264.  
  265. 2 is multiplied by 16 (or left shifted 4 times) then the next digit (0) is
  266. added to it. [ == 32]
  267.  
  268. 32 XOR xorstring[08] = 'a'
  269.  
  270. Move to the next two digits and repeat -
  271.   4 * 16 = 64
  272.   64 + 14 (E) = 78
  273.   increment the index into the xor string
  274.   78 XOR xorstring[08] = 'b'
  275.  
  276. In a couple of days you should be able to download a PalmPilot version of
  277. this and a FORTH interpretation with instructions to put it into your
  278. OpenBoot prom on SPARCs from the l0pht (www.l0pht.com).
  279.  
  280. Just figured I'd point out where those two pieces of code came from since
  281. attribution was lacking in the previous posts.
  282.  
  283. .mudge
  284.  
  285.  
  286. ----------------------------------------------------------------------------------
  287.  
  288.  
  289.   Here begins 'decrypt.c' which contains code cleanups
  290.   on the decryption stuff. By jared@puck.nether.net.
  291.  
  292.  
  293. #include <stdio.h>
  294. #include <ctype.h>
  295.  
  296. char xlat[] = {
  297.         0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f,
  298.         0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72,
  299.         0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44
  300. };
  301.  
  302. char pw_str1[] = " password 7 ";
  303. char pw_str2[] = "enable password 7 ";
  304. char pw_str3[] = "ip ftp password 7 ";
  305. char pw_str4[] = " ip ospf message-digest-key 1 md5 7 ";
  306.  
  307. char *pname;
  308.  
  309. cdecrypt(enc_pw, dec_pw)
  310. char *enc_pw;
  311. char *dec_pw;
  312. {
  313.         unsigned int seed, i, val = 0;
  314.  
  315.         if(strlen(enc_pw) & 1)
  316.                 return(-1);
  317.  
  318.         seed = (enc_pw[0] - '0') * 10 + enc_pw[1] - '0';
  319.  
  320.         if (seed > 15 || !isdigit(enc_pw[0]) || !isdigit(enc_pw[1]))
  321.                 return(-1);
  322.  
  323.         for (i = 2 ; i <= strlen(enc_pw); i++) {
  324.                 if(i !=2 && !(i & 1)) {
  325.                         dec_pw[i / 2 - 2] = val ^ xlat[seed++];
  326.                         val = 0;
  327.                 }
  328.  
  329.                 val *= 16;
  330.  
  331.                 if(isdigit(enc_pw[i] = toupper(enc_pw[i]))) {
  332.                         val += enc_pw[i] - '0';
  333.                         continue;
  334.                 }
  335.  
  336.                 if(enc_pw[i] >= 'A' && enc_pw[i] <= 'F') {
  337.                         val += enc_pw[i] - 'A' + 10;
  338.                         continue;
  339.                 }
  340.  
  341.                 if(strlen(enc_pw) != i)
  342.                         return(-1);
  343.         }
  344.  
  345.         dec_pw[++i / 2] = 0;
  346.  
  347.         return(0);
  348. }
  349.  
  350. usage()
  351. {
  352.         fprintf(stdout, "Usage: %s -p <encrypted password>\n", pname);
  353.         fprintf(stdout, "       %s <router config file> <output file>\n", pname);
  354.  
  355.         return(0);
  356. }
  357.  
  358. main(argc,argv)
  359. int argc;
  360. char **argv;
  361.  
  362. {
  363.         FILE *in = stdin, *out = stdout;
  364.         char line[257];
  365.         char passwd[65];
  366.         unsigned int i, pw_pos;
  367.  
  368.         pname = argv[0];
  369.  
  370.         if(argc > 1)
  371.         {
  372.                 if(argc > 3) {
  373.                         usage();
  374.                         exit(1);
  375.                 }
  376.  
  377.                 if(argv[1][0] == '-')
  378.                 {
  379.                         switch(argv[1][1]) {
  380.                                 case 'h':
  381.                                 usage();
  382.                                 break;
  383.  
  384.                                 case 'p':
  385.                 bzero(passwd, sizeof(passwd));
  386.                                 if(cdecrypt(argv[2], passwd)) {
  387.                                         fprintf(stderr, "Error.\n");
  388.                                         exit(1);
  389.                                 }
  390.                                 fprintf(stdout, "password: %s\n", passwd);
  391.                                 break;
  392.  
  393.                                 default:
  394.                                 fprintf(stderr, "%s: unknow option.", pname);
  395.                         }
  396.  
  397.                         return(0);
  398.                 }
  399.  
  400.                 if((in = fopen(argv[1], "rt")) == NULL)
  401.                         exit(1);
  402.                 if(argc > 2)
  403.                         if((out = fopen(argv[2], "wt")) == NULL)
  404.                                 exit(1);
  405.         }
  406.  
  407.         while(1) {
  408.                 for(i = 0; i < 256; i++) {
  409.                         if((line[i] = fgetc(in)) == EOF) {
  410.                                 if(i)
  411.                                         break;
  412.  
  413.                                 fclose(in);
  414.                                 fclose(out);
  415.                                 return(0);
  416.                         }
  417.                         if(line[i] == '\r')
  418.                                 i--;
  419.  
  420.                         if(line[i] == '\n')
  421.                                 break;
  422.                 }
  423.                 pw_pos = 0;
  424.                 line[i] = 0;
  425.  
  426.                 if(!strncmp(line, pw_str1, strlen(pw_str1)))
  427.                         pw_pos = strlen(pw_str1);
  428.  
  429.                 if(!strncmp(line, pw_str2, strlen(pw_str2)))
  430.                         pw_pos = strlen(pw_str2);
  431.         if(!strncmp(line, pw_str3, strlen(pw_str3)))
  432.             pw_pos = strlen(pw_str3);
  433.         if(!strncmp(line, pw_str4, strlen(pw_str4)))
  434.             pw_pos = strlen(pw_str4);
  435.  
  436.                 if(!pw_pos) {
  437.                         fprintf(stdout, "%s\n", line);
  438.                         continue;
  439.                 }
  440.  
  441.         bzero(passwd, sizeof(passwd));
  442.                 if(cdecrypt(&line[pw_pos], passwd)) {
  443.                         fprintf(stderr, "Error.\n");
  444.                         exit(1);
  445.                 }
  446.                 else {
  447.                         if(pw_pos == strlen(pw_str1))
  448.                                 fprintf(out, "%s", pw_str1);
  449.                         else if (pw_pos == strlen(pw_str2))
  450.                                 fprintf(out, "%s", pw_str2);
  451.             else if (pw_pos == strlen(pw_str3))
  452.                 fprintf(out, "%s", pw_str3);
  453.             else if (pw_pos == strlen(pw_str4))
  454.                 fprintf(out, "%s", pw_str4);
  455.  
  456.  
  457.                         fprintf(out, "%s\n", passwd);
  458.                 }
  459.         }
  460. }
  461.  
  462.  
  463.  
  464. -----------------------------------------------------------------------------
  465.  
  466.  
  467. >           I've done a few code cleanups on the decryption stuff and put
  468. >   it up for ftp with these fixes.. i have a few more to make
  469. >   so it'll just grab it from bgp sessions, ospf keys, etc..
  470. >
  471. >           Get it from ftp://puck.nether.net/pub/jared/decrypt.c
  472.  
  473. It does not work reliably for passwords longer than eight characters.
  474. The problem is that Cisco passwords can be 11 character long, and if the
  475. initial seed is larger than 10, the translation table is too short.
  476. The full translation table is as follows:
  477.  
  478. char xlat[] = {
  479.         0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f,
  480.         0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72,
  481.         0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44, 0x48, 0x53 , 0x55, 0x42
  482. };
  483.  
  484. This copes also with the case when the passwords that are 11 character long and
  485. the seed is 15.
  486.  
  487. Janos Zsako
  488.  
  489. PS. The passwords longer than 11 characters are allowed, however they are
  490. truncated to the first 11 characters (just as they are to 8 in most Unix
  491. implementations).
  492.  
  493.  
  494. -----------------------------------------------------------------------------
  495.  
  496.  
  497. A non-Cisco source has recently released a new program to decrypt user
  498. passwords (and other passwords) in Cisco configuration files. The program
  499. will not decrypt passwords set with the "enable secret" command.
  500.  
  501. The unexpected concern that this program has caused among Cisco customers
  502. has led us to suspect that many customers are relying on Cisco password
  503. encryption for more security than it was designed to provide. This document
  504. explains the security model behind Cisco password encryption, and the
  505. security limitations of that encryption.
  506.  
  507. User Passwords
  508. - --------------
  509. User passwords and most other passwords (*not* enable secrets) in Cisco IOS
  510. configuration files are encrypted using a scheme that's very weak by modern
  511. cryptographic standards.
  512.  
  513. Although Cisco does not distribute a decryption program, at least two
  514. different decryption programs for Cisco IOS passwords are available to the
  515. public on the Internet; the first public release of such a program of which
  516. Cisco is aware was in early 1995. We would expect any amateur cryptographer
  517. to be able to create a new program with no more than a few hours' work.
  518.  
  519. The scheme used by IOS for user passwords was never intended to resist a
  520. determined, intelligent attack; it was designed to avoid casual
  521. "over-the-shoulder" password theft. The threat model was someone reading a
  522. password from an administrator's screen. The scheme was never supposed to
  523. protect against someone conducting a determined analysis of the
  524. configuration file.
  525.  
  526. Because of the weak encryption algorithm, it has always been Cisco's
  527. position that customers should treat any configuration file containing
  528. passwords as sensitive information, the same way they would treat a
  529. cleartext list of passwords.
  530.  
  531. Enable Secret Passwords
  532. - -----------------------
  533. Enable secrets are hashed using the MD5 algorithm. As far as anyone at
  534. Cisco knows, it is impossible to recover an enable secret based on the
  535. contents of a configuration file (other than by obvious dictionary
  536. attacks).
  537.  
  538. Note that this applies only to passwords set with "enable secret", *not*
  539. to passwords set with "enable password". Indeed, the strength of the
  540. encryption used is the only significant difference between the two
  541. commands.
  542.  
  543. Other Passwords
  544. - ---------------
  545. Almost all passwords and other authentication strings in Cisco IOS
  546. configuration files are encrypted using the weak, reversible scheme used
  547. for user passwords. To determine which scheme has been used to encrypt a
  548. specific password, check the digit preceding the encrypted string in the
  549. configuration file. If that digit is a 7, the password has been encrypted
  550. using the weak algorithm. If the digit is a 5, the password has been hashed
  551. using the stronger MD5 algorithm.
  552.  
  553. For example, in the configuration command
  554.  
  555.     enable secret 5 $1$iUjJ$cDZ03KKGh7mHfX2RSbDqP.
  556.  
  557. The enable secret has been hashed with MD5, whereas in the command
  558.  
  559.     username jbash password 7 07362E590E1B1C041B1E124C0A2F2E206832752E1A01134D
  560.  
  561. The password has been encrypted using the weak reversible algorithm.
  562.  
  563. Can the algorithm be changed?
  564. - -----------------------------
  565. Cisco has no immediate plans to support a stronger encryption algorithm for
  566. IOS user passwords. Should Cisco decide to introduce such a feature in the
  567. future, that feature will definitely impose an additional ongoing
  568. administrative burden on users who choose to take advantage of it.
  569.  
  570. It is not, in the general case, possible to switch user passwords over to
  571. the MD5-based algorithm used for enable secrets, because MD5 is a one-way
  572. hash, and the password can't be recovered from the encrypted data at all.
  573. In order to support certain authentication protocols (notably CHAP), the
  574. system needs access to the clear text of user passwords, and therefore must
  575. store them using a reversible algorithm.
  576.  
  577. Key management issues would make it a nontrivial task to switch over to a
  578. stronger reversible algorithm, such as DES. Although it would be easy to
  579. modify IOS to use DES to encrypt passwords, there would be no security
  580. advantage in doing so if all IOS systems used the same DES key. If
  581. different keys were used by different systems, an administrative burden
  582. would be introduced for all IOS network administrators, and portability of
  583. configuration files between systems would be damaged. Customer demand
  584. for stronger reversible password encryption has been small.
  585.  
  586. November 10, 1997
  587.  
  588.  
  589. -----------------------------------------------------------------------------
  590.  
  591.